package com.hfzy.ihk.common.core.elasticsearch.base;

import com.alibaba.fastjson.JSON;
import com.hfzy.ihk.common.constants.GlobalStatic;
import com.hfzy.ihk.common.core.elasticsearch.ElasticsearchOperation;
import com.hfzy.ihk.common.core.elasticsearch.OperationErrorMsgBiz;
import com.hfzy.ihk.common.core.elasticsearch.anotations.BestDoSupport;
import com.hfzy.ihk.common.support.Result;
import com.hfzy.ihk.common.support.aop.AspectjHelper;
import com.hfzy.ihk.common.util.string.StringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Administrator on 2018/6/7.
 * 非主业务逻辑操作管理器
 * /*
 * 这个AopContext.currentProxy() == 被拦截的类实例；例如：TestEntityBiz$$EnhancerBySpringCGLIB$$374000d6
 OperationHandler handler = ((OperationManager)AopContext.currentProxy()).getHandlerMap().get(key);

 到底使用cglib还是jdk动态代理来处理aop，和该类是否有父类有直接关系！！！！！！！！！！！！！！
 * @author wws
 */
@Aspect
@Component
@ConditionalOnProperty(prefix = "linkcall.elasticsearch",name = "enable")
public class OperationManager implements InitializingBean,ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(AspectjHelper.class);

    @Autowired(required = false)
    private List<OperationHandler> handlers;
    @Autowired
    private OperationErrorMsgBiz operationErrorMsgBiz;

    private ApplicationContext context;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    private static ConcurrentHashMap<String,OperationHandler> handlerMap = new ConcurrentHashMap<>(50);

    @Pointcut("@annotation(com.hfzy.ihk.common.core.elasticsearch.anotations.BestDoSupport)")
    void bestDo() {
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        if(handlers == null || handlers.size()==0){
            logger.warn("未检测到存在operationHandler,请检查程序是否正常。");
            return;
        }

        for(OperationHandler handler : handlers){
            String key = StringUtil.strConnect(handler.getTable().getTableName(),":",handler.getTableOperation().getOperationName());
            handlerMap.put(key,handler);
            logger.debug("init handleMap:key:{},handler:{}",key,handler);
        }

    }


    @AfterReturning(value = "bestDo()", returning = "returnRs")
    protected void bestDoAfterReturn(JoinPoint joinPoint, Object returnRs) {

        try {
            logger.debug("param:" + JSON.toJSONString(joinPoint.getArgs()));
            logger.debug("returnRs is:" + JSON.toJSONString(returnRs));

            BestDoSupport annotation = AspectjHelper.getMethodAnnotation(joinPoint, BestDoSupport.class);

            boolean needDoOperation = annotation.needDoOperation();
            boolean needSendKafkaMessage = annotation.needSendKafkaMessage();
            boolean needReturnSuccess = annotation.needReturnSuccess();

            if(needReturnSuccess){

                if(!checkRsIsSuccess((Result) returnRs)){
                    return;
                }
            }

            if(needDoOperation) {
                doOpt(joinPoint, returnRs);
            }

            if(needSendKafkaMessage){
                //TODO 待支持
                doSend(joinPoint,returnRs);
            }
        } finally {
            BestDoContextHolder.clearOperation();
            BestDoContextHolder.clearTransactionId();
        }

    }

    @AfterThrowing(value = "bestDo()")
    protected void bestDoAfterThrowingException(){
        BestDoContextHolder.clearOperation();
        BestDoContextHolder.clearTransactionId();
    }

    protected void doOpt(JoinPoint joinPoint,Object returnRs) {

        List<ElasticsearchOperation> elasticsearchOperationList =  BestDoContextHolder.allOperation();

        for(ElasticsearchOperation operation : elasticsearchOperationList){

            String key = StringUtil.strConnect(operation.getOptTable(),":",operation.getOptMethod());

            OperationHandler handler = handlerMap.get(key);

            if(handler == null) {
                logger.warn("找不到对应的操作处理器，key:" + key + ",请检查。");
                operationErrorMsgBiz.dealElasticsearchOperation(operation,null);
                return;
            }

            handler.handle(operation);
        }

    }

    @Async
    protected void doSend(JoinPoint joinPoint,Object returnRs) {
        List<String> msgList = BestDoContextHolder.allMessage();
//        for()
    }

    protected boolean checkRsIsSuccess(Result returnRs){

        if(returnRs == null) {
            return false;
        }

        if(GlobalStatic.CODE_1.equals(returnRs.getCode())) {
            return true;
        }
        return false;
    }

    public static ConcurrentHashMap<String, OperationHandler> getHandlerMap() {
        return handlerMap;
    }
}
